#include "Epoll.h"
#include <cstdio>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <strings.h>
#include "Channel.h"
#include <cassert>
#include <unistd.h>
#include <sys/syscall.h>
#include "Log.h"

Epoll::Epoll()
{
    if ((m_epollfd = epoll_create(1)) == -1) // 创建epoll句柄（红黑树）。
    {
        char buf[256]={0};
        char* ret=strerror_r(errno, buf, sizeof(buf));        
        LOG(ERROR)<<"epoll_create() failed."<<ret<<"("<<errno<<")";
        exit(-1);
    }
}

Epoll::~Epoll()
{
    ::close(m_epollfd);
}

void Epoll::update_channel(Channel *channel)
{
    //todo 为什么这里需要加锁，不然会报错？
    std::lock_guard<std::mutex> lock(m_mutex);
    epoll_event ev;
    ev.data.ptr = channel;
    ev.events = channel->events();
    if (channel->in_epoll())
    {
        if (epoll_ctl(m_epollfd, EPOLL_CTL_MOD, channel->fd(), &ev) == -1)
        {
            char buf[256]={0};
            char* ret=strerror_r(errno, buf, sizeof(buf));        
            LOG(ERROR)<<"epoll_ctl() EPOLL_CTL_MOD failed."<<ret<<"("<<errno<<")";
            exit(-1);
        }
    }
    else
    {
        if (epoll_ctl(m_epollfd, EPOLL_CTL_ADD, channel->fd(), &ev) == -1)
        {
            char buf[256]={0};
            char* ret=strerror_r(errno, buf, sizeof(buf));        
            LOG(ERROR)<<"epoll_ctl() EPOLL_CTL_ADD failed."<<ret<<"("<<errno<<")";
            //LOG(ERROR)<<"fd:"<< channel->fd()<<" in_epoll:"<<channel->in_epoll();;
            exit(-1);
        }
        channel->set_inepoll();
        //LOG(INFO)<<"set_inepoll "<<"fd:"<<channel->fd()<<" in_epoll:"<<channel->in_epoll();
    }
}

void Epoll::remove_channel(Channel *channel)
{
    if (channel->in_epoll()) 
    {       
        if (epoll_ctl(m_epollfd,EPOLL_CTL_DEL,channel->fd(),0)==-1)
        {
            char buf[256]={0};
            char* ret=strerror_r(errno, buf, sizeof(buf));        
            LOG(ERROR)<<"epoll_ctl() EPOLL_CTL_DEL failed."<<ret<<"("<<errno<<")";
            exit(-1);
        }
    }
    //todo 修改的bug,
    channel->set_not_inepoll();
    //LOG(INFO)<<"set_not_inepoll "<<"fd:"<<channel->fd()<<" in_epoll:"<<channel->in_epoll();

}

std::vector<Channel *> Epoll::loop(int timeout)
{
    std::vector<Channel *> channels;

    //-1表示阻塞，直到有事件发生
    // 如果infds>0，表示有事件发生的fd的数量。
    int infds = epoll_wait(m_epollfd, m_events, M_MAX_EVENTS, timeout);

    // 返回失败。
    if (infds < 0)
    {
        char buf[256]={0};
        char* ret=strerror_r(errno, buf, sizeof(buf));        
        LOG(ERROR)<<"epoll_wait() failed."<<ret<<"("<<errno<<")";
        exit(1);
    }

    // 超时。
    if (infds == 0)
    {
        return channels;
    }

    for (int i = 0; i < infds; i++)
    {
        Channel *ch = (Channel *)m_events[i].data.ptr;
        ch->set_revents(m_events[i].events);
        channels.push_back(ch);
    }
    return channels;
}